using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading;
using Bentley.GenerativeComponents.Features;
using Bentley.GenerativeComponents.Features.Specific;
using Bentley.GenerativeComponents.GeneralPurpose;
using Bentley.GenerativeComponents.GCScript;
using Bentley.GenerativeComponents.GCScript.GCTypes;
using Bentley.GenerativeComponents.GCScript.Namescopes;

namespace Bentley.GenerativeComponents.Features
{
    static internal class ResponsiveGCPreliminariesv08
    {
        private static GC_IO_UIv08 gcUI;

        static internal void Load()
        {
#if DEBUG
            TextWriterTraceListener tr = new TextWriterTraceListener(System.IO.File.CreateText
                ("DebugLog\\" + System.DateTime.Now.ToString("yyMd_HHmm") + "_ResponsiveGC.txt"));
            Debug.Listeners.Add(tr);
#endif

            Debug.WriteLine("Starting ResponsiveGC");
            Debug.Flush();
            
            // This method is called from within the constructor of the class, Initializer (within this project).

            NameCatalog nameCatalog = NamescopeTools.GetStandardNameCatalogForUser();
            nameCatalog.AddNamespaceLevelFunction("ConnectUbi", "void function()", ConnectToUbiMash);
            nameCatalog.AddNamespaceLevelFunction("DisconnectUbi", "void function()", Disconnect);
            nameCatalog.AddNamespaceLevelFunction("SubscribeAll", "void function()", SubscribeAllVars);
            nameCatalog.AddNamespaceLevelFunction("SubscribePointList", "void function()", SubscribePointList); 
        }

        /// <summary>Connect to Ubimash</summary>
        static private void ConnectToUbiMash(CallFrame frame)
        {
            try
            {    
                 // Walk the Symbolic model and print a list of variables and their values.      
                 // Use the following technique to get the "native" .NET values of the given arguments.
                 //CoordinateSystem aBaseCS = frame.UnboxArgument<CoordinateSystem>(0);     // Get the first argument (i.e., the argument at index 0) as a .NET CoordinateSystem value                
                Dictionary<string, GraphVariable> variablesInModel;
                 //Graph activeSymbolicGraph = GCTools.UserGraphDomain.Graph;
                Graph activeSymbolicGraph = GCTools.UserGraphDomain.Graph;
                 variablesInModel = CollectVariablesAndValues(activeSymbolicGraph);

                 if (variablesInModel.Count > 0)
                 {
                    //Feature.SendErrorReport(String.Concat("Found ", variablesInModel.Count, " variables: "));
                    foreach (KeyValuePair<string, GraphVariable> aVar in variablesInModel)
                    {
                       Debug.WriteLine(String.Concat(aVar.Key, "=", aVar.Value.Value));
                    }
                    
                    gcUI = new GC_IO_UIv08(variablesInModel);
                    gcUI.Show();
                 }
                 else
                 {
                    Debug.WriteLine("No variables found");
                 }
                
            }
            catch (Exception e)
            {
                Debug.WriteLine("Exception in Connect: " + e.Message);
                Debug.WriteLine(e.StackTrace);
            }
        }

        /// <summary>Disconnect from Ubimash</summary>
        static private void Disconnect(CallFrame frame)
        {
            try
            {
                if (gcUI != null)
                {
                    gcUI.DisconnectFromUbimash();                    
                    gcUI.Close();
                    gcUI.Dispose();
                }
            }
            catch (Exception e)
            {               
                Debug.WriteLine("Exception in Disconnect: " + e.Message);
                Debug.WriteLine(e.StackTrace);
            }
        }
           
        /// <summary>Connect to Ubimash and Subscribe all GC variables automatically to PubSubServer</summary>
        static private void SubscribeAllVars(CallFrame frame)
        {
            try
            {
                // Walk the Symbolic model and print a list of variables and their values.      
                // Use the following technique to get the "native" .NET values of the given arguments.
                //CoordinateSystem aBaseCS = frame.UnboxArgument<CoordinateSystem>(0);     // Get the first argument (i.e., the argument at index 0) as a .NET CoordinateSystem value                
                Dictionary<string, GraphVariable> variablesInModel;
                
                Graph activeSymbolicGraph = GCTools.UserGraphDomain.Graph;
                variablesInModel = CollectVariablesAndValues(activeSymbolicGraph);

                if (variablesInModel.Count > 0)
                {   
                    gcUI = new GC_IO_UIv08(variablesInModel);

                    Debug.WriteLine("Variables found:");
                    Debug.Flush();

                    foreach (KeyValuePair<string, GraphVariable> aVar in variablesInModel)
                    {
                        Debug.WriteLine(String.Concat(aVar.Key, "=", aVar.Value.Value));
                        Debug.Flush();

                        gcUI.Subscribe(aVar.Key, aVar.Key, false);
                    }

                    gcUI.Show();
                }
                else
                {
                    Debug.WriteLine("No variables found");
                    Debug.Flush();
                }                                                      
                
            }
            catch (Exception e)
            {
                Debug.WriteLine(e.Message);
                Debug.Flush();
            }
        }

        /// <summary>Connect to Ubimash and Subscribe all GC variables to PointList sent to PubSubServer</summary>
        static private void SubscribePointList(CallFrame frame)
        {
            try
            {
                // Walk the Symbolic model and print a list of variables and their values.      
                // Use the following technique to get the "native" .NET values of the given arguments.
                Dictionary<string, GraphVariable> variablesInModel;

                Graph activeSymbolicGraph = GCTools.UserGraphDomain.Graph;
                variablesInModel = CollectVariablesAndValues(activeSymbolicGraph);

                if (variablesInModel.Count > 0)
                {
                    gcUI = new GC_IO_UIv08(variablesInModel);

                    Debug.WriteLine("Variables found:");
                    Debug.Flush();

                    foreach (KeyValuePair<string, GraphVariable> aVar in variablesInModel)
                    {
                        Debug.WriteLine(String.Concat(aVar.Key, "=", aVar.Value.Value));
                        Debug.Flush();

                        gcUI.Subscribe(aVar.Key, aVar.Key, true);
                    }

                    gcUI.Show();
                }
                else
                {
                    Debug.WriteLine("No variables found");
                    Debug.Flush();
                }

            }
            catch (Exception e)
            {
                Debug.WriteLine(e.Message);
                Debug.Flush();
            }
        }

        ///// <summary>Connect to servo and publish GC variables update</summary>
        //static private void PublishToServo(CallFrame frame)
        //{
        //    try
        //    {
        //        // Walk the Symbolic model and print a list of variables and their values.      
        //        // Use the following technique to get the "native" .NET values of the given arguments.
                
        //        Dictionary<string, GraphVariable> variablesInModel;
                
        //        Graph activeSymbolicGraph = GCTools.UserGraphDomain.Graph;
        //        variablesInModel = CollectVariablesAndValues(activeSymbolicGraph);

        //        if (variablesInModel.Count > 0)
        //        {
        //            //Feature.SendErrorReport(String.Concat("Found ", variablesInModel.Count, " variables: "));

        //            //if (variablesInModel.Count > 6)

        //            gcUI = new GC_IO_UIv08(variablesInModel);

        //            Debug.WriteLine("Variables found:");
        //            Debug.Flush();

        //            foreach (KeyValuePair<string, GraphVariable> aVar in variablesInModel)
        //            {
        //                Debug.WriteLine(String.Concat(aVar.Key, "=", aVar.Value.Value));
        //                Debug.Flush();                  
        //            }
        //            gcUI.PublishToServo();
        //            gcUI.Show();
        //        }
        //        else
        //        {
        //            Debug.WriteLine("No variables found");
        //        }


                
        //    }
        //    catch (Exception e)
        //    {
        //        //Feature.SendErrorReport("Error in connecting and starting GC_IO_UI " + e.ToString());
        //    }
        //}

         ////<summary>
         ////Acknowledgment: Steve Downing, Arup and DesignLink SDK
         ////Collect a Dictionary of GC Variable names and their values.
         ////</summary>
         ////<param name="aGraph"></param>
         ////<returns></returns>
        private static Dictionary<string, GraphVariable> CollectVariablesAndValues(Graph aGraph)
        {
            Dictionary<string, GraphVariable> variablesInModel = new Dictionary<string, GraphVariable>();
            // Walk down the tree
            foreach (Feature aFeature in aGraph.Nodes())
            {
                if (aFeature.GetType() == typeof(GraphVariable))
                {
                    //Cast it to a graph variable
                    GraphVariable aGrapVar = (GraphVariable)aFeature;
                    variablesInModel.Add(aGrapVar.Name, aGrapVar);
                }
            }
            return variablesInModel;
        }

    }
}
